///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_IMAGE_CIMAGEGC_H_
#define _BUOLA_IMAGE_CIMAGEGC_H_

#include <buola/image/cgc.h>
#include <buola/image/rasterizer/cscanlinerasterizer.h>
#include <buola/image/rasterizer/cstroker.h>

namespace buola { namespace img {

namespace detail {
    
    class CImageGCBase : public CGC
    {
    protected:
        CImageGCBase(const CSize_d &pSize);
        
    private:
        void DoFill();
        void DoStroke();
        void DoClip();
        void DoResetClip();
        virtual void DoRender(CScanlineRasterizer<> &pRasterizer)=0;
        
        CSize_d mSize;
        bool mClip;
        CScanlines mClipArea;
    };
    
/*namespace detail*/ }
    
template<typename tFormat>
class CImageGC : public detail::CImageGCBase
{
public:
    CImageGC(const CMView<tFormat> &pImage)
        :   detail::CImageGCBase(pImage.Size())
        ,   mImage(pImage)
    {}

    CSurface *Surface() {   return nullptr; }

    void Paint() {}
private:
    void DoRender(CScanlineRasterizer<> &pRasterizer);

    void DrawGlyphs(PFont pFont,TFontIndex pIndex,int *pIndices,int pN,
                    const std::vector<CTextLayout::SGlyph> &pGlyphs,const CPoint_d &pPos) {}

    void Composite(const CPoint_d &pDstPoint,const CSize_d &pDstSize,const img::CPicture &pSrc,
                   const CPoint_d &pSrcPoint=nZero,const CSize_d &pSrcSize=nUndefined,
                   const img::CPicture &pMask=img::CPicture(),const CPoint_d &pMaskPoint=nZero,
                   const CSize_d &pMaskSize=nUndefined,img::EExtend pExtend=img::EExtend::NONE) {}
public:
    CMView<tFormat> mImage;
};

template<typename tFormat>
class CImageSolidRenderer
{
public:
    CImageSolidRenderer(const CMView<tFormat> &pView,const CPixel<tFormat> &pPixel)
        :   mView(pView)
        ,   mPixel(pPixel)
    {}
    
    void RenderPixel(int x,int y,int pCoverage)
    {
        mView(x,y).Blend(mPixel,pCoverage);
    }
    
    void RenderHLine(int x,int y,int w,int pCoverage)
    {
        blend_hline(mView,x,y,w,mPixel,pCoverage);
    }
    
    void RenderSpans(int y,int *pXs,int *pLens,uint8_t *pAlphas,int n)
    {
        auto lIt=mView.Row(y).begin();

        for(int i=0;i<n;i++)
        {
            auto lIt2=lIt+pXs[i];
            int lAlpha=pAlphas[i];
            if(lAlpha==255)
            {
                for(int j=0;j<pLens[i];j++)
                {
                    *(lIt2++)=mPixel;
                }
            }
            else
            {
                for(int j=0;j<pLens[i];j++)
                {
                    (*(lIt2++)).Blend(mPixel,lAlpha);
                }
            }
        }
    }
    
private:
    const CMView<tFormat> &mView;
    CPixel<tFormat> mPixel;
};

template<typename tFormat>
class CImageSolidRowRenderer
{
public:
    CImageSolidRowRenderer(const CMView<tFormat> &pView,const CPixel<tFormat> &pPixel)
        :   mView(pView)
        ,   mPixel(pPixel)
    {}
    
    void StartRow(int y)
    {
        mIt=mView.Row(y).begin();
    }
    
    void RenderPixel(int x,int pCoverage)
    {
        mIt[x].Blend(mPixel,pCoverage);
    }
    
    void RenderHLine(int x,int w,int pCoverage)
    {
        auto lIt=mIt+x;
        if(pCoverage==255)
        {
            while(w--)
            {
                (*lIt)=mPixel;
                ++lIt;
            }
        }
        else
        {
            while(w--)
            {
                (*lIt).Blend(mPixel,pCoverage);
                ++lIt;
            }
        }
    }
        
private:
    const CMView<tFormat> &mView;
    typename CMView<tFormat>::TXIterator mIt;
    CPixel<tFormat> mPixel;
};

template<typename tFormat>
void CImageGC<tFormat>::DoRender(CScanlineRasterizer<> &pRasterizer)
{
//    CImageSolidRenderer<tFormat> lRenderer(mImage,Source().Color());
//    CImageSolidRowRenderer<tFormat> lRenderer(mImage,Source().Color());
//    lRasterizer.RenderScanlinesRows(lRenderer);
    pRasterizer.RenderScanlines(mImage,Source().Color());
}

/*namespace img*/ } /*namespace buola*/ }

#endif
